/*
* Copyright (C) 2008-2009 J-P Nurmi jpnurmi@gmail.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* $Id: mainwindow.cpp 595 2009-09-28 17:27:05Z jpnurmi $
*/

#include "mainwindow.h"
#include "application.h"
#include "connectionwizard.h"
#include "sessiontabwidget.h"
#include "maintabwidget.h"
#include "connection.h"
#include "homeview.h"
#include "session.h"
#include <QtGui>

MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
{
    tabWidget = new MainTabWidget(this);
    connect(tabWidget, SIGNAL(alertStatusChanged(bool)), this, SLOT(activateAlert(bool)));
    setCentralWidget(tabWidget);

    if (QSystemTrayIcon::isSystemTrayAvailable())
    {
        trayIcon = new TrayIcon(this);
        trayIcon->setIcon(QApplication::windowIcon());
        trayIcon->setVisible(true);
        connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
            this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason)));
    }

    QShortcut* shortcut = new QShortcut(QKeySequence::ZoomIn, this);
    connect(shortcut, SIGNAL(activated()), qApp, SLOT(zoomIn()));

    shortcut = new QShortcut(QKeySequence::ZoomOut, this);
    connect(shortcut, SIGNAL(activated()), qApp, SLOT(zoomOut()));

    shortcut = new QShortcut(QKeySequence(tr("Ctrl+Q")), this);
    connect(shortcut, SIGNAL(activated()), this, SLOT(close()));

    QSettings settings;
    if (!restoreGeometry(settings.value("geometry").toByteArray()))
        resize(800, 600);

    homeView = new HomeView(tabWidget);
    connect(homeView, SIGNAL(connectTo(Connection)), this, SLOT(connectTo(Connection)));
    connect(homeView, SIGNAL(connectToImpl(Connection)), this, SLOT(connectToImpl(Connection)));
    tabWidget->addTab(homeView, HomeView::tr("Home"));

    QTimer::singleShot(0, this, SLOT(initialize()));
}

void MainWindow::connectTo(const QString& host, quint16 port, const QString& nick, const QString& password)
{
    Connection conn;
    conn.host = host;
    conn.port = port;
    conn.nick = nick;
    conn.pass = password;
    connectTo(conn);
}

void MainWindow::connectTo(const Connection& connection)
{
    ConnectionWizard wizard;
    wizard.setConnection(connection);

    if (!connection.host.isEmpty() && !connection.nick.isEmpty())
    {
        connectToImpl(connection);
    }
    else if (wizard.exec())
    {
        Connection connection = wizard.connection();
        if (!connection.name.isEmpty())
        {
            Application::setConnections(Application::connections() << connection);
            homeView->updateContent();
        }
        connectToImpl(connection);
    }
}

void MainWindow::connectToImpl(const Connection& connection)
{
    Session* session = new Session(this);
    connect(session, SIGNAL(connected()), this, SLOT(connected()));
    connect(session, SIGNAL(reconnecting()), this, SLOT(reconnecting()));
    connect(session, SIGNAL(disconnected()), this, SLOT(disconnected()));
    session->connectTo(connection);

    SessionTabWidget* tab = new SessionTabWidget(session, tabWidget);
    connect(tab, SIGNAL(disconnectFrom(QString)), this, SLOT(disconnectFrom(QString)));
    connect(tab, SIGNAL(titleChanged(QString)), tabWidget, SLOT(setSessionTitle(QString)));
    connect(tab, SIGNAL(alertStatusChanged(bool)), tabWidget, SLOT(activateAlert(bool)));
    connect(tab, SIGNAL(highlightStatusChanged(bool)), tabWidget, SLOT(activateHighlight(bool)));
    connect(tabWidget, SIGNAL(currentChanged(int)), tab, SLOT(delayedTabReset()));
    int index = tabWidget->addTab(tab, session->host());
    tabWidget->setTabAnimation(index, true);
}

void MainWindow::disconnectFrom(const QString& message)
{
    SessionTabWidget* tab = qobject_cast<SessionTabWidget*>(sender());
    if (!tab)
        tab = qobject_cast<SessionTabWidget*>(tabWidget->currentWidget());
    Q_ASSERT(tab);
    QString reason = message.trimmed();
    if (reason.isEmpty())
        reason = tr("%1 %2 - %3").arg(Application::applicationName())
        .arg(Application::applicationVersion())
        .arg(Application::organizationDomain());
    tab->session()->quit(reason);
    tab->session()->disconnectFromServer();
    // automatically rejoin channels when reconnected
    tab->session()->setAutoJoinChannels(tab->channels());
}

void MainWindow::quit(const QString& message)
{
    // TODO: confirm?
    for (int i = 0; i < tabWidget->count(); ++i)
    {
        SessionTabWidget* tab = qobject_cast<SessionTabWidget*>(tabWidget->widget(i));
        QString reason = message.trimmed();
        if (reason.isEmpty())
            reason = tr("%1 %2 - %3").arg(Application::applicationName())
                                     .arg(Application::applicationVersion())
                                     .arg(Application::organizationDomain());
        tab->session()->quit(reason);
        tab->session()->disconnectFromServer();
    }
    close();
}

void MainWindow::closeEvent(QCloseEvent* event)
{
    QSettings settings;
    settings.setValue("geometry", saveGeometry());

    QMainWindow::closeEvent(event);
}

void MainWindow::changeEvent(QEvent* event)
{
    QMainWindow::changeEvent(event);
    if (event->type() == QEvent::ActivationChange)
    {
        if (isActiveWindow())
            trayIcon->unalert();
    }
}

void MainWindow::initialize()
{
    foreach (const Connection& connection, Application::connections())
    {
        if (connection.autoConnect)
            connectToImpl(connection);
    }
    if (Application::connections().isEmpty())
        connectTo(Connection());
}

void MainWindow::connected()
{
    for (int i = 0; i < tabWidget->count(); ++i)
    {
        SessionTabWidget* tab = qobject_cast<SessionTabWidget*>(tabWidget->widget(i));
        if (tab && tab->session() == sender())
            tabWidget->setTabAnimation(i, false);
    }
}

void MainWindow::reconnecting()
{
    for (int i = 0; i < tabWidget->count(); ++i)
    {
        SessionTabWidget* tab = qobject_cast<SessionTabWidget*>(tabWidget->widget(i));
        if (tab && tab->session() == sender())
            tabWidget->setTabAnimation(i, true);
    }
}

void MainWindow::disconnected()
{
    /*for (int i = 0; i < tabWidget->count(); ++i)
    {
        SessionTabWidget* tab = qobject_cast<SessionTabWidget*>(tabWidget->widget(i));
        if (tab && tab->session() == sender())
            tabWidget->setTabEnabled(i, false);
    }*/
}

void MainWindow::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
{
    switch (reason)
    {
        case QSystemTrayIcon::DoubleClick:
            setVisible(!isVisible());
            break;
        case QSystemTrayIcon::Trigger:
            raise();
            activateWindow();
            break;
        default:
            break;
    }
}

void MainWindow::activateAlert(bool activate)
{
    if (!isActiveWindow())
    {
        if (activate)
        {
            trayIcon->alert();
            QApplication::alert(this);
        }
        else
        {
            trayIcon->unalert();
        }
    }
}
